import { FileStream } from 'egg';
import * as fs from 'fs';
import * as path from 'path';
import { v4 as uuidv4 } from 'uuid';
import * as PizZip from 'pizzip';

const Docxtemplater = require('docxtemplater');
const ImageModule = require('open-docxtemplater-image-module');

interface saveQuestionnaireResultDocxParam {
  epilog: string,
  mergeUuid: string,
  fileType: string,
  title: string,
  description: string,
  physicalResult: string,
  mentalAnxiety: string,
  mentalDepression: string,
  mentalParanoid: string,
  mentalPsychotic: string,
  mentalWellBeing: string,
  stressWorkLoad: string,
  stressCompany: string,
  stressLeaderShip: string,
  stressColleagues: string,
  stressCustomers: string,
  stressFamily: string,
  solutionResult: string,
  concludedImagePath: string,
  physicalImagePath: string,
  mentalImagePath: string,
  stressImagePath: string,
  solutionImagePath: string,
  isView?: boolean
}
const isStringArray = (
  clearFilepath: string | string[],
): clearFilepath is string[] => (clearFilepath instanceof Array);

class FileUtil {
  static saveImage(stream: FileStream, filename: string) {
    return new Promise((resolve, reject) => {
      const uuid = uuidv4();
      const filenameSplitedArr = filename.split('.');
      const suffix = filenameSplitedArr[filenameSplitedArr.length - 1];
      const curFilename = `${uuid}.${suffix}`;
      const absolutePath = path.resolve(
        __dirname,
        '../public/image',
        curFilename
      );

      const writeStream = fs.createWriteStream(absolutePath);
      stream.pipe(writeStream);
      stream.on('error', reject);
      stream.on('end', () => {
        resolve(curFilename);
      });
    });
  }

  static readImage(filename: string) {
    let stream;

    try {
      const absolutePath = path.resolve(
        __dirname,
        '../public/image',
        filename
      );

      stream = fs.createReadStream(absolutePath);
    } catch (error) {
      console.log(error);
    }

    return stream;
  }

  static async saveQuestionnaireResultFile({
    mergeUuid,
    epilog,
    title,
    description,
    physicalResult,
    mentalAnxiety,
    mentalDepression,
    mentalParanoid,
    mentalPsychotic,
    mentalWellBeing,
    stressWorkLoad,
    stressCompany,
    stressLeaderShip,
    stressColleagues,
    stressCustomers,
    stressFamily,
    solutionResult,
    concludedImagePath,
    physicalImagePath,
    mentalImagePath,
    stressImagePath,
    solutionImagePath,
    isView
  }: saveQuestionnaireResultDocxParam) {
    const templateResolvePath = path.resolve(
      __dirname,
      isView ? '../public/temp/template-view.docx' : '../public/temp/template.docx'
    );
    const userDocxResolvePath = path.resolve(
      __dirname,
      isView ? `../public/word/${mergeUuid}-view.docx` : `../public/word/${mergeUuid}.docx`
    );

    // 获取文件
    let content: string | null = fs.readFileSync(
      templateResolvePath,
      'binary'
    );

    let zip: PizZip | null = null;
    if (content) {
      zip = new PizZip(content);
    }

    const getImage = (tagValue: string) => fs.readFileSync(tagValue);

    const getSize = (_img, _tagValue, tagName) => {
      if (tagName === 'physicalImage' || tagName === 'solutionImage') {
        return [450, 200];
      }
      return [450, 350];
    };

    const opts = {
      centered: true,
      getImage,
      getSize,
      fileType: 'docx'
    };
    const imageModule = new ImageModule(opts);
    try {
      const doc = new Docxtemplater()
        .attachModule(imageModule)
        .loadZip(zip)
        .setData({
          epilog,
          title,
          description,
          physicalResult,
          mentalAnxiety,
          mentalDepression,
          mentalParanoid,
          mentalPsychotic,
          mentalWellBeing,
          stressWorkLoad,
          stressCompany,
          stressLeaderShip,
          stressColleagues,
          stressCustomers,
          stressFamily,
          solutionResult,
          concludedImage: concludedImagePath,
          physicalImage: physicalImagePath,
          mentalImage: mentalImagePath,
          stressImage: stressImagePath,
          solutionImage: solutionImagePath
        })
        .render();

      let buf = doc
        .getZip()
        .generate({ type: 'nodebuffer' });
      fs.writeFileSync(
        path.resolve(
          userDocxResolvePath
        ), buf
      );

      buf = null;
    } catch (error) {
      console.error(error);
      throw new Error('问卷反馈Word生成错误');
    }

    // this.delayClearFile([
    //   userDocxResolvePath,
    //   physicalImagePath,
    //   mentalImagePath,
    //   stressImagePath,
    //   solutionImagePath
    // ], 1000 * 60 * 60 * 12);

    content = null;
    zip = null;

    return userDocxResolvePath;
  }

  // FIXME: 或许有更好的方法。
  /**
   * 延迟清除文件
   * @param clearFilepath 清除文件的路径
   * @param delay 延迟，单位 ms
   */
  static delayClearFile(clearFilepath: string[], delay: number) {
    if (isStringArray(clearFilepath)) {
      clearFilepath.forEach((_path) => {
        setTimeout(() => fs.unlink(_path), delay);
      });

      return;
    }

    setTimeout(() => fs.unlink(clearFilepath), delay);
  }
}

export default FileUtil;
